#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Logging utilities for the visualization engine
"""

import logging
import sys
from typing import Optional
from datetime import datetime
import os


def setup_logging(
    level: str = "INFO",
    log_file: Optional[str] = None,
    format_string: Optional[str] = None
) -> None:
    """
    设置日志配置
    
    Args:
        level: 日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)
        log_file: 日志文件路径，如果为None则只输出到控制台
        format_string: 自定义日志格式
    """
    if format_string is None:
        format_string = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    
    # 配置根日志器
    logging.basicConfig(
        level=getattr(logging, level.upper()),
        format=format_string,
        handlers=[]
    )
    
    # 添加控制台处理器
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(logging.Formatter(format_string))
    logging.getLogger().addHandler(console_handler)
    
    # 添加文件处理器（如果指定了文件）
    if log_file:
        # 确保日志目录存在
        os.makedirs(os.path.dirname(log_file), exist_ok=True)
        
        file_handler = logging.FileHandler(log_file, encoding='utf-8')
        file_handler.setFormatter(logging.Formatter(format_string))
        logging.getLogger().addHandler(file_handler)


def get_logger(name: str) -> logging.Logger:
    """
    获取指定名称的日志器
    
    Args:
        name: 日志器名称
        
    Returns:
        logging.Logger: 日志器实例
    """
    return logging.getLogger(name)


class EngineLogger:
    """引擎专用日志器"""
    
    def __init__(self, name: str = "DataEngine"):
        self.logger = get_logger(name)
        self._session_id = None
    
    def set_session_id(self, session_id: str) -> None:
        """设置会话ID"""
        self._session_id = session_id
    
    def _format_message(self, message: str) -> str:
        """格式化消息，添加会话ID"""
        if self._session_id:
            return f"[{self._session_id}] {message}"
        return message
    
    def debug(self, message: str, **kwargs) -> None:
        """记录调试信息"""
        self.logger.debug(self._format_message(message), **kwargs)
    
    def info(self, message: str, **kwargs) -> None:
        """记录信息"""
        self.logger.info(self._format_message(message), **kwargs)
    
    def warning(self, message: str, **kwargs) -> None:
        """记录警告"""
        self.logger.warning(self._format_message(message), **kwargs)
    
    def error(self, message: str, **kwargs) -> None:
        """记录错误"""
        self.logger.error(self._format_message(message), **kwargs)
    
    def critical(self, message: str, **kwargs) -> None:
        """记录严重错误"""
        self.logger.critical(self._format_message(message), **kwargs)
    
    def log_execution_time(self, operation: str, execution_time: float) -> None:
        """记录执行时间"""
        self.info(f"操作 '{operation}' 执行时间: {execution_time:.3f}秒")
    
    def log_data_info(self, df_shape: tuple, operation: str = "") -> None:
        """记录数据信息"""
        rows, cols = df_shape
        message = f"数据形状: {rows}行 x {cols}列"
        if operation:
            message = f"{operation} - {message}"
        self.info(message)
    
    def log_error_with_context(self, error: Exception, context: dict) -> None:
        """记录带上下文的错误"""
        error_message = f"错误: {str(error)}"
        if context:
            context_str = ", ".join([f"{k}={v}" for k, v in context.items()])
            error_message += f" | 上下文: {context_str}"
        self.error(error_message)


# 全局日志器实例
engine_logger = EngineLogger()


def log_function_call(func):
    """装饰器：记录函数调用"""
    def wrapper(*args, **kwargs):
        func_name = func.__name__
        engine_logger.debug(f"调用函数: {func_name}")
        
        start_time = datetime.now()
        try:
            result = func(*args, **kwargs)
            execution_time = (datetime.now() - start_time).total_seconds()
            engine_logger.log_execution_time(func_name, execution_time)
            return result
        except Exception as e:
            execution_time = (datetime.now() - start_time).total_seconds()
            engine_logger.error(f"函数 {func_name} 执行失败 (耗时: {execution_time:.3f}秒): {str(e)}")
            raise
    
    return wrapper 